package ch.bfh.ti.barcode.multiple;


/**
 * This frame is the first frame transfered and carries additional information
 * like the filename and the file size.
 * 
 * @author Dominik von Burg
 * 
 */
class HeaderFrame extends Frame {
	/**
	 * Create a HeaderFrame by providing the user data and additional
	 * parameters.
	 * 
	 * @param data
	 *            The user data.
	 * @param size
	 *            The size of the user data in all the frames.
	 * @param totalFrames
	 *            The total amount of frames.
	 * @param filename
	 *            The filename. Can be empty.
	 * @param errorCorrectionLevel
	 *            After how many frames an error correction frame should be
	 *            sent.
	 */
	public HeaderFrame(byte[] data, int size, int totalFrames, String filename,
			int errorCorrectionLevel) {
		frame = new byte[data.length+headerSize];

		filename = shortenFilename(filename);
		System.arraycopy(data, 0, frame, headerSize, data.length);
		frame[0] = (byte) 0;
		frame[1] = (byte) 0;
		frame[2] = (byte) ((totalFrames << 24) >>> 24);
		frame[3] = (byte) ((totalFrames << 16) >>> 24);
		frame[4] = (byte) ((size << 24) >>> 24);
		frame[5] = (byte) ((size << 16) >>> 24);
		frame[6] = (byte) ((size << 8) >>> 24);
		frame[7] = (byte) (size >>> 24);
		frame[8] = (byte) ((errorCorrectionLevel << 24) >>> 24);
		byte[] f = filename.getBytes();
		System.arraycopy(f, 0, frame, headerSize - filenameSize, f.length);
	}

	/**
	 * Create a HeaderFrame by passing the raw data. All the additional data has
	 * to be included in header of the raw data.
	 * 
	 * @param data
	 *            The raw data of the frame.
	 */
	public HeaderFrame(byte[] data) {
		frame = data;
	}

	/**
	 * Reads the error correction level from the header of the frame.
	 * 
	 * @return After how many frames an error correction frame should be sent.
	 */
	public int getErrorCorrectionLevel() {
		return frame[8] & 0xff;
	}

	/**
	 * Reads the total frame aount from the header of the frame.
	 * 
	 * @return The total frame amount.
	 */
	public int getTotalFrames() {
		int totalFrames = frame[2] & 0xff;
		totalFrames += (frame[3] & 0xff) << 8;
		return totalFrames;
	}

	/**
	 * Reads the size of the user data from the header of the frame.
	 * 
	 * @return The size of the user data in bytes.
	 */
	public int getSize() {
		int size = frame[4] & 0xff;
		size += (frame[5] & 0xff) << 8;
		size += (frame[6] & 0xff) << 16;
		size += (frame[7] & 0xff) << 24;
		return size;
	}

	/**
	 * Reads the filename from the header of the frame.
	 * 
	 * @return The filename.
	 */
	public String getFilename() {
		byte[] f = new byte[filenameSize];
		System.arraycopy(frame, headerSize - filenameSize, f, 0, f.length);
		return new String(f).replaceAll("\u0000.*", "");
	}

	private String shortenFilename(String name) {
		if (name.length() <= filenameSize)
			return name;

		return name.substring(0, filenameSize - 4)
				+ name.substring(name.length() - 4);
	}
}
